#include "StdAfx.h"
#include "SHA1.h"
#include "AccountMgr.h"


AccountMgr::AccountMgr(Database::IDatabase* pAccountDB) : m_pAccountDB(pAccountDB)
{
}


AccountMgr::~AccountMgr(void)
{
}

void AccountMgr::Update()
{
	Database::IQueryResult* res = m_pAccountDB->Query("SELECT * FROM account /*WHERE password_sha1 = ''*/");
	if(res)
	{
		std::string username = "";
		std::string password = "";
		std::string query = "";

		do
		{
			std::stringstream ss;

			uint64 id = res->Fetch()[0].ToUInt64();
			username = res->Fetch()[1].ToString();
			password = res->Fetch()[2].ToString();
			std::string password_sha1 = res->Fetch()[3].ToString();

			std::transform(username.begin(), username.end(), username.begin(), toupper);
			std::transform(password.begin(), password.end(), password.begin(), toupper);

			if(password_sha1.empty() == false)
			{
				Crypt::BigNumber num;
				num.SetHexStr(password_sha1.c_str());
				Account acc(num, username, password, id);
				mLock.lock();
				m_Accounts[id] = acc;
				mLock.unlock();
				continue;
			}

			ss << username << ":";
			ss << password;

			Crypt::SHA1 sha;
			uint8 hash[SHA_DIGEST_LENGTH] = "";

			sha.update(ss.str());

			sha.getDigest(hash);
			char hashTmp[SHA_DIGEST_LENGTH * 2 + 1] = { 0 };
			for(uint32 i = 0; i < SHA_DIGEST_LENGTH; ++i) {
				sprintf(hashTmp + i * 2, "%02X", hash[i]);
			}

			password_sha1 = hashTmp;
			Crypt::BigNumber num(password_sha1);
			Account acc(num, username, password, id);
			mLock.lock();
			m_Accounts[id] = acc;
			mLock.unlock();

			query = "UPDATE account SET password_sha1 = '" + m_pAccountDB->EscapeString(password_sha1);
			query += "', password = '' WHERE ID = '" + res->Fetch()[0].ToString() + "'";

			if(m_pAccountDB->Execute(query) == false)
				throw Exception();
		} while(res->NextRow());
		delete res;
	}
}

bool AccountMgr::getAccount(const std::string& name, Account& acc) {
	std::string accUpper(name);
	std::transform(name.begin(), name.end(), accUpper.begin(), toupper);
	mLock.lock();
	for(auto itr = m_Accounts.begin(); itr != m_Accounts.end(); ++itr) {
		if(itr->second.GetUsername() == accUpper) {
			acc = itr->second;
			mLock.unlock();
			return true;
		}
	}
	mLock.unlock();
	return false;
}